#pragma once
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <istream>
#include <iostream>
#include <ostream>
#include <deque>

#include "icmp_header.h"
#include "ipv4_header.h"
#include "network_check_interface.h"

using boost::asio::ip::icmp;
using boost::asio::deadline_timer;
namespace posix_time = boost::posix_time;

class pinger :public INetworkCheckHelper
{
public:
	pinger(std::function<void(Network_Status s)>);
	~pinger();
	virtual bool startCheck(const char* destination)override;
	virtual bool stopCheck() override;
private:
	void start_send();
	void handle_timeout();
	void start_receive();
	void handle_receive(std::size_t length);
	void startPingThread();
	static unsigned short get_identifier();
	void network_evaluate();
private:
	boost::asio::io_service m_io_service;
private:
	icmp::resolver resolver_;
	icmp::endpoint destination_;
	icmp::socket socket_;
	deadline_timer timer_;
	unsigned short sequence_number_;
	posix_time::ptime time_sent_;
	boost::asio::streambuf reply_buffer_;
	std::size_t num_replies_;
private:
	std::atomic<bool> m_start_flag = false;
	std::function<void(Network_Status s)> m_network_status_callback;
	std::deque<size_t>  m_fiveLatestPacketsEcho;
	size_t              m_loss = 0;
	std::string         m_destination;
	std::mutex          m_lock_mutex;
	std::thread         m_ping_thread;
	size_t              m_nTimes = 0;
};